home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Mousetools
/
MenuStay
/
MenuStay.ez
< prev
next >
Wrap
Text File
|
1996-09-26
|
16KB
|
737 lines
*--------------------------------------------------------------------------
* MenuStay V1.0
; is FreeWare
; With this small tool it's now possible to go around the menus
; without holding the right mouse button.
; Just press AND release the right mouse button over the wished menubar.
; In the menu-stay-mode it's possible
; to add a command to items that don't have one,
; by pressing the left mouse button.
; To activate the screen blanker
; just press and release the cursor up and down keys simultaneous.
; Once installed, this tool only uses 568 bytes of memory.
; To get back to normal simply run the program again.
; No need to 'RUN' or 'RUNBACK' this tool from the CLI.
; 1993 by Alexandros Loghis
* Sun Apr 18 21:25:19 1993
;:-)
* Some information about this source code
; All routines where taken from
; Preben Nielsen's RMBShift V1.0 assembly source (thanks),
; exept the input handler that was written by myself.
; The whole program was (re)written in
; Joe Siebenmann's EZAsm V1.6 (Fish 592).
; Assembled with Charlie Gibbs A68k V2.71.
; EZAsm combines parts of "C" with 68000 assembly, giving it the "feel"
; of a higher level language.
; The resulting code is optimized as much as possible.
*--------------------------------------------------------------------------
include "exec/io.i"
include "exec/memory.i"
include "exec/interrupts.i"
include "devices/input.i"
include "devices/inputevent.i"
include "libraries/dosextens.i"
include "hardware/custom.i"
include "hardware/dmabits.i"
include "intuition/intuitionbase.i"
include "intuition/intuition.i"
*--------------------------------------------------------------------------
LONG _DosBase WBMsg PProcess HMem
*--------------------------------------------------------------------------
Main PProcess = FindTask( 0 )
a2 = d0
pr_CLI(a2) = 0 l {
WaitPort( &pr_MsgPort(a2) ) ;WBStart
WBMsg = GetMsg( &pr_MsgPort(a2) )
}
_DosBase = OldOpenLibrary( &DosName(pc) )
beq.s Error
lea IntBase(pc),a2
(a2) = OldOpenLibrary( &IntName(pc) )
beq.s Error
lea IHSName(pc),a1
bsr FindThisPort
beq.s DoInstall
DoRemove
CloseLibrary( IntBase(pc) )
moveq #REMOVED,d7 because of the forward reference
lea IHS(pc),a0
lea PSEndIHS1(pc),a1
lea PSEndIHS2(pc),a2
bsr RemoveHandler
beq.s ShowMsg
moveq #CANTREMOVE,d7
bra.s ShowMsg
DoInstall
moveq #INSTALLED,d7
lea IHS(pc),a0
lea PSPrepIHS1(pc),a1
lea PSPrepIHS2(pc),a2
bsr InstallHandler
beq.s ShowMsg
moveq #CANTINSTALL,d7
ShowMsg d0 = d7 l
bsr.s CONMsg
Error _DosBase != 0 {
CloseLibrary( _DosBase )
}
WBMsg != 0 {
Forbid( )
ReplyMsg( WBMsg )
}
END
*--------------------------------------------------------------------------
* Console message routines
;Writes a general copyright message and then a more specific message.
;Writes to standard output when run from CLI, and opens its own window
;when run from Workbench.
; >= D0 = Msg-number
FHandle equr d5
CONMsg movem.l d0-d7/a0-a6,-(sp)
d4 = d0
d6 = 0
FHandle = Output( )
bne.s 1$
d6 = 1
lea CONName(pc),a0
FHandle = Open( a0 #MODE_OLDFILE )
beq.s exit
1$ moveq #INFOMSG,d0
bsr.s SendMsg
d0 = d4
bsr.s SendMsg
d6 != 0 {
Delay( 127 )
Close( FHandle )
}
exit movem.l (sp)+,d0-d7/a0-a6
rts
*-------------
; >= d0 = Msg-number
SendMsg neg.l d0
d0 << 1
lea CONMsgTable(pc),a0
a0 += 0(a0,d0.l) w
d2 = a0
d3 = -1
1$ d3 ++
(a0)+ != 0 b
bne.s 1$
Write( FHandle * * )
rts
INFOMSG = 0
INSTALLED = -1
REMOVED = -2
CANTINSTALL = -3
CANTREMOVE = -4
CONText MACRO
dc.w \1-CONMsgTable
ENDM
CONMsgTable CONText Msg
CONText Msg1
CONText Msg2
CONText Msg3
CONText Msg4
CONName dc.b 'CON:100/60/330/63/MenuStay',0
Msg dc.b 10,$9B,'0;33m MenuStay V1.0 '
dc.b $9B,'0;31mis FreeWare',10
dc.b ' 1993 by ',$9B,'0;33mAlexandros Loghis'
dc.b $9B,'0;31m',10,' ',0
Msg1 dc.b 'has now been installed...',10,0
Msg2 dc.b 'has now been removed...',10,0
Msg3 dc.b "Error: Can't install handler",10,0
Msg4 dc.b "Error: Can't remove handler",10,0
even
*--------------------------------------------------------------------------
* Inputhandler removal and installation routines
; This is general-purpose inputhandler removal-routine
; It only needs an ihs with a port-name to remove the handler
; >= a0 = ihs
; >= a1 = first ihs-installation-routine or NULL
; >= a2 = second ihs-installation-routine or NULL
; => d0 = 0 means succes
rtsValue equr d7
RemoveHandler
movem.l d1/rtsValue/a0-a3/a6,-(sp)
moveq #-1,rtsValue weil EZAsm über d7 opt. will
a3 = a2
a2 = a0
d1 = a1
beq.s 1$
jsr (a1) ; a0 = ihs
beq.s 2$
a2 = d0
1$ a0 = a2
d0 = #IND_REMHANDLER
bsr.s TellInputDevice
rtsValue = d0
bne.s 2$
RemPort( &ihs_Port(A2) )
d0 = 0
bra.s 3$
2$ d0 = -1
3$ d1 = a3
beq.s 4$
a0 = a2
jsr (a3) ; a0 = ihs, d0 = 0 means succes
4$ d0 = rtsValue
movem.l (sp)+,d1/rtsValue/a0-a3/a6
rts
*-------------
; This is general-purpose inputhandler installation-routine
; It only needs an ihs with a port-name to install the handler
; >= a0 = ihs
; >= a1 = first ihs-installation-routine or NULL
; >= a2 = second ihs-installation-routine or NULL
; => d0 = 0 means succes
InstallHandler
movem.l d1/rtsValue/a0-a3/a6,-(sp)
moveq #-1,rtsValue else EZAsm will optimize using d7
a3 = a2
a2 = a0
d1 = a1
beq.s 1$
jsr (a1) ; a0 = ihs
beq.s 2$
a2 = d0
1$ a0 = a2
d0 = #IND_ADDHANDLER
bsr.s TellInputDevice
rtsValue = d0 l
bne.s 2$
lea ihs_Port(a2),a1
MP+LN_NAME(A1) = ihs_PortName(A2) l ;MsgPort->mp_Node.ln_Name=Name
MP+LN_PRI(A1) = 0 b ;MsgPort->mp_Node.ln_Pri = 0
MP+LN_TYPE(A1) = #NT_MSGPORT b ;MsgPort->mp_Node.ln_Type=NT_MSGPORT
MP_FLAGS(A1) = #PA_IGNORE b ;MsgPort->mp_Flags = PA_IGNORE
AddPort( * )
d0 = 0
bra.s 3$
2$ d0 = -1
3$ d1 = a3
beq.s 4$
a0 = a2
jsr (a3) ; a0 = ihs, d0 = 0 means succes
4$ d0 = rtsValue
movem.l (sp)+,D1/rtsValue/A0-A3/A6
rts
*-------------
; Open the input device. Set up the I/O block to add or remove the
; input handler, and send the request to the input device. Finally,
; close the device
; >= a0 = ihs
; >= d0 = Function to perform (IND_ADDHANDLER/IND_REMHANDLER)
; => d0 = 0 means succes
Size = IOSTD_SIZE+MP_SIZE
IReq = -IOSTD_SIZE
IPort = -MP_SIZE-IOSTD_SIZE
TellInputDevice
link a5,#-Size until unlk use of EZAsm variables not allowed
movem.l d0/a5,-(sp)
d0 = #Size-1 w
1$ -(a5) = 0 b
dbra d0,1$
movem.l (sp)+,d0/a5
movem.l d1-d2/rtsValue/a0-a3/a6,-(sp)
moveq #-1,rtsValue else EZAsm will optimize using d7
d2 = d0
a2 = a0
lea IPort(a5),a3
MP+LN_TYPE(a3) = #NT_MSGPORT b ; mp_Node.ln_Type=NT_MSGPORT;
MP_FLAGS(a3) = #PA_SIGNAL b ; mp_Flags =PA_SIGNAL;
AllocSignal( -1 )
MP_SIGBIT(a3) = d0 b ; mp_SigBit =MPSigBit;
bmi.s exit2
FindTask( 0 )
MP_SIGTASK(a3) = d0 l ; mp_SigTask =FindTask(0);
lea MP_MSGLIST(a3),a0
NEWLIST a0
lea IReq(a5),a1
; ExtReq->io_Message.mn_ReplyPort=taskReplyPort;
IO+MN_REPLYPORT(a1) = a3 l
; ExtReq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
IO+MN+LN_TYPE(a1) = #NT_MESSAGE b
OpenDevice( &InputName(pc) 0 * 0 )
D0 = 0 w { ; flag: error if > 0
lea IReq(a5),a1
IO_COMMAND(a1) = d2 w
lea ihs_Interrupt(a2),a0
IO_DATA(a1) = a0 l
rtsValue = DoIO( * )
CloseDevice( &IReq(a5) )
}
d0 = MP_SIGBIT(a3) b
FreeSignal( * )
exit2 d0 = rtsValue
movem.l (sp)+,d1-d2/rtsValue/a0-a3/a6
unlk a5
rts
*-------------
; Each handler should have such a pair of installation-routines.
; The first one is passed to InstallHandler in A1, and it
; is called immediately when entering InstallHandler.
; The second one is passed to InstallHandler in A2, and it
; is called if installation of handler and message-port succeeds.
; >= a0 = ihs
; => d0 has to point to ihs to be used when installation proceeds.
; If d0 = 0 then installation is aborted.
PSPrepIHS1
movem.l d1/a0-a1/a6,-(sp)
HMem = AllocMem( #HandlerSize #MEMF_PUBLIC|MEMF_CLEAR )
beq.s 2$
a1 = d0
lea IHS(pc),a0
d0 = #HandlerSize
movem.l d0/a0-a1,-(sp)
CopyMem( * * * )
movem.l (sp)+,d0/a0-a1
ihs_Length(a1) = d0 l ; This will enable removal by other programs
lea HandlerCode-IHS(a1),a0
ihs_Interrupt+IS_CODE(a1) = a0 ; ihs_Interrupt.is_Code = Handler
ihs_Interrupt+IS_DATA(a1) = 0 l ; ihs_Interrupt.is_Data = 0
lea IHSName-IHS(a1),a0
ihs_PortName(A1) = a0 l ; ihs_PortName = IHSName
; ihs_Interrupt.is_Node.ln_Pri = HPRI
ihs_Interrupt+LN_PRI(a1) = #HPRI b
d0 = a1
2$ movem.l (sp)+,d1/a0-a1/a6
rts
*-------------
; >= a0 = ihs
; => d0 = 0 means everything went perfect
; -1 means something went wrong during installation
PSPrepIHS2
movem.l d0-d1/a0-a1/a6,-(sp)
d0 != 0 {
d0 != HMem {
FreeMem( d0 #HandlerSize )
}
}
movem.l (sp)+,d0-d1/a0-a1/a6
rts
*-------------
; Each handler should have such a pair of ending-routines.
; The first one is passed to RemoveHandler in A1, and it
; is called immediately when entering RemoveHandler.
; The second one is passed to RemoveHandler in A2, and it
; is called if removal of handler and message-port succeeds.
; >= a0 = ihs
; => d0 has to point to ihs to be used when removal proceeds
; If D0 = 0 then removal is aborted
PSEndIHS1
-(sp) = a1
lea IHSName(pc),a1
bsr.s FindThisPort
a1 = (sp)+
rts
*-------------
; >= a0 = ihs
; => d0 = 0 means everything went perfect
; -1 means something went wrong during removal
PSEndIHS2
movem.l d0-d1/a0-a1/a6,-(sp)
d0 >= 0 {
FreeMem( a0 ihs_Length(a0) )
}
movem.l (sp)+,d0-d1/a0-a1/a6
rts
*-------------
; >= a1 = Portname
; => d0 = Port or NULL (cc reflects result also)
FindThisPort
movem.l d1-d2/a0-a1/a6,-(sp)
d2 = a1
Forbid( )
d2 = FindPort( d2 )
Permit( )
d0 = d2
movem.l (sp)+,d1-d2/a0-a1/a6
rts
*--------------------------------------------------------------------------
* Input-handler start
ihs_Port = 0
ihs_Interrupt = MP_SIZE
ihs_ID = MP_SIZE+IS_SIZE
ihs_Length = MP_SIZE+IS_SIZE+4
ihs_Flags = MP_SIZE+IS_SIZE+8
ihs_PortName = MP_SIZE+IS_SIZE+10
ihs_LocalArea = MP_SIZE+IS_SIZE+14
ihs_SIZE = MP_SIZE+IS_SIZE+14
ihs_Start MACRO
dcb.b MP_SIZE,0 ; Message-Port structure
dcb.b IS_SIZE,0 ; Interrupt structure
dc.l 'P_IH' ; ID
dc.l 0 ; Length of handler
dc.w 0 ; Flags
dc.l 0
ENDM
HPRI = 55
HDisabled = 0
HNoExtRemoval = 1
; This is the handler-block
IHS ihs_Start
; Put local data here
IfBlanker dc.b 0 must be before IfRMBDown !
IfRMBDown dc.b 0 must be after IfBlanker !
IntBase dc.l 0
RawKeyBuffer dcb.w 5,0 last 5 pressed keys
RKBLastElem = *-2
; IHS name
IHSName dc.b 'MenuStay V1.0 Port',0
even
; For each event in the event list:
; If we were waiting for this event then signal the task.
; When all the events have been checked, return the event list so that
; others can do their things.
Next = ie_NextEvent
Class = ie_Class
Code = ie_Code
Qual = ie_Qualifier
EList equr a0
Event equr a1
Tmp equr a2
BPtr equr a3 Raw key buffer pointer
WPtr equr a3 Active window pointer
Dma equr a4
IfB equr a5 Ptr to IfBlanker
IfRD equr a5 IfRMBDown
RegLst reg Event/EList/Tmp/BPtr/Dma/IfB/d1
*-------------
TstHPos tst.b vhposr-dmacon(Dma)
bne.s TstHPos
btst #0,vposr+1-dmacon(Dma)
bne.s TstHPos
rts
*-------------
* Change these constants to activate the blanker with an other key combination
Key1Up equ $cc Raw key code from cursor up when released
Key1Dn equ $4c " " pressed
Key2Up equ $cd Raw key code from cursor down when released
Key2Dn equ $4d " " pressed
TstUp cmp.w #Key1Up,-(BPtr)
beq.s 1$
cmp.w #Key2Up,(BPtr)
1$ rts
TstDwn subq.l #2,BPtr
TstDwn2 cmp.w #Key1Dn,(BPtr)
beq.s 1$
cmp.w #Key2Dn,(BPtr)
1$ rts
*-------------
TstBlanker
(IfB) != 0 {
bsr.s TstHPos
(Dma) = #DMAF_SETCLR|DMAF_COPPER|DMAF_RASTER w
(IfB) -- b
}
rts
*-------------
; >= a0 = List of InputEvents
; >= a1 = HandlerData
HandlerCode
movem.l RegLst,-(sp)
Event = EList l
ieLoop d0 = Event
beq NoMoreEvents
lea $dff000+dmacon,Dma
lea IfBlanker(pc),IfB
cmpi.b #IECLASS_RAWKEY,Class(Event)
bne.s NxtTst
bsr.s TstBlanker
d0 = Code(Event) w
cmp.w RKBLastElem(pc),d0 still pressing the same key ?
beq.s NxtTst yes
lea RawKeyBuffer(pc),BPtr prepare
lea RawKeyBuffer+2(pc),Tmp to
d0 = #(RKBLastElem-RawKeyBuffer-1)/2 ; shift
1$ (BPtr)+ = (Tmp)+ w ; the
dbra d0,1$ ; RawKeyBuffer
(BPtr)+ = Code(Event) w ; enter actual key
bsr.s TstUp test if the 2 key where pressed
bne.s NxtTst
bsr.s TstUp
beq.s 2$
bsr.s TstDwn2
bne.s NxtTst
bsr.s TstUp and then if there where released
bne.s NxtTst
2$ bsr.s TstDwn
bne.s NxtTst
bsr.s TstDwn
bne.s NxtTst
bsr TstHPos wait until start of raster
(Dma) = #DMAF_COPPER|DMAF_RASTER w ; screen
color-dmacon(Dma) = 0 w ; and
spr+4-dmacon(Dma) = 0 l ; mouse blanking
(IfB) ++ b ; set flag to true
NxtTst
cmpi.b #IECLASS_RAWMOUSE,Class(Event)
bne.s NxtEv
bsr.s TstBlanker
IfRD ++ l ; IfB is from now tabu
cmpi.w #IECODE_LBUTTON,Code(Event)
beq.s PressLMB
cmpi.w #IECODE_RBUTTON,Code(Event)
beq.s PressRMB
cmpi.w #IECODE_UP_PREFIX|IECODE_RBUTTON,Code(Event)
bne.s NxtEv
ReleaseRMB
tst.b (IfRD)
beq.s NxtEv
bsr.s TstMenuBar
bcs.s DontRemove
bra.s clear
PressRMB
(IfRD) = 0 {
bsr.s TstMenuBar
bcc.s NxtEv
(IfRD) ++ b
bra.s NxtEv
}
clear (IfRD) = 0
DontRemove
(IfRD) != 0 {
Class(Event) = 0 w ; Kill event (make it an IECLASS_NULL event)
(IfRD) ++ b ; (IfRD) = 2 = staymode on
}
NxtEv Event = Next(Event) l ; Just move on to next Event
bra ieLoop
NoMoreEvents
d0 = EList
movem.l (sp)+,RegLst
rts
*-------------
TstMenuBar
Tmp = IntBase(pc) l
WPtr = ib_ActiveWindow(Tmp) l
wd_MenuStrip(WPtr) != 0 l { ; if exists
Tmp = ib_ActiveScreen(Tmp) l
d0 = sc_MouseY(Tmp) w
d0 < #$100 w {
d0 < sc_BarHeight(Tmp) b
}
}
rts ; carry flag = 1 means MousePtr in menubar
*-------------
CHARNR equ 256 array length
lft equr d0 left border
rght equr d1 right "
Mn equr a2
Item equr a3
HiIt equr a4 Highlighted item
Base equr a5 Base address from array of ASCII codes
PressLMB
cmp.b #2,(IfRD) ; (IfRD) = 2 = staymode on
bne.s NxtEv
Base = sp l
lea -CHARNR(sp),sp
d0 = #(CHARNR/4)-1
1$ -(Base) = 0 l ; clear array
dbra d0,1$ Base = sp
Tmp = IntBase(pc) l
Tmp = ib_ActiveWindow(Tmp) l
Mn = wd_MenuStrip(Tmp) l
sub.l HiIt,HiIt
Menus d0 = mu_FirstItem(Mn) l
beq.s noItems
bsr.s RekSrch
noItems Mn = mu_NextMenu(Mn) l
d0 = Mn
bne.s Menus
d0 = HiIt ; any item highlighted ?
beq.s exit3 no
tst.b mi_Command(HiIt) command already exists ?
bne.s exit3 yes
moveq #'Z'-'A',rght = 25
bigEQsm 'A'(Base,rght.w) != 0 b { ; big letters command = small
'a'(Base,rght.w) ++ b ; letters com.
}
'A'(Base,rght.w) ++ b ; don't use big letters commands
rght -- b
bpl.s bigEQsm until negative
moveq #'a',lft small
moveq #'z',rght letters
bsr.s ChrSrch
beq.s found
moveq #'0',lft numbers
moveq #'9',rght
bsr.s ChrSrch
beq.s found
moveq #'!',lft all printable
moveq #'~',rght chars
bsr.s ChrSrch
bne.s exit3 not found
found mi_Command(HiIt) = lft b ; set command
or.w #COMMSEQ,mi_Flags(HiIt) set command flag
Class(Event) = 0 w ; Kill event (make it an IECLASS_NULL event)
exit3 lea CHARNR(sp),sp
bra NxtEv
*-------------
RekSrch ; rekursive searching throught items
Item = d0
d0 = mi_Flags(Item) w
d0 &= #HIGHITEM w ; Test if item currently highlighted
beq.s 1$ no
HiIt = Item l
d0 = 0
1$ d0 = mi_Command(Item) b ; get char
0(Base,d0.w) ++ b ; mark it in the array
d0 = mi_SubItem(Item)
beq.s noSubIt
-(sp) = Item l
bsr.s RekSrch
Item = (sp)+ l
noSubIt d0 = mi_NextItem(Item)
bne.s RekSrch
rts
*-------------
ChrSrch ; search for the first unused char that is >= lft & <= rght
0(Base,lft.w) != 0 b {
lft ++ b
cmp.b rght,lft
bls.s ChrSrch
}
rts ; zero flag = 1 then a char was found
*-------------
HandlerSize = *-IHS
*--------------------------------------------------------------------------
DosName dc.b "dos.library",0
even
InputName dc.b "input.device",0
even
IntName dc.b "intuition.library",0
even